/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sunrise.entity;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import static javax.persistence.CascadeType.ALL;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import org.primefaces.model.ScheduleEvent;

/**
 *
 * @author frank
 */
@Entity
@NamedQueries({
    @NamedQuery(name = Event.findAll, query = "SELECT e FROM Event e"),
    @NamedQuery(name = Event.findOutdoorEvents, query = "SELECT e FROM Event e WHERE e.outdoor = TRUE"),
    @NamedQuery(name = Event.findByCalendar, query = "SELECT e FROM Event e WHERE e.calendar = :calendar"),
    @NamedQuery(name = Event.findByUser, query = "SELECT e FROM Event e INNER JOIN Calendar c ON e.calendar = c WHERE c.owner = :owner"),
    @NamedQuery(name = Event.findByIdentifier, query = "SELECT e FROM Event e WHERE e.identifier = :identifier"),
    @NamedQuery(name = Event.findByUserInvitationAccepted,
            query = "SELECT e FROM Event e, InvitationRequest i WHERE i.event = e AND i.recipient = :user and i.accepted=TRUE")

})
public class Event implements Serializable, ScheduleEvent {

    private static final long serialVersionUID = 1L;

    public static final String findAll = "Event.findAll";
    public static final String findOutdoorEvents = "Event.findOutdoorEvents";
    public static final String findByCalendar = "Event.findByCalendar";
    public static final String findByUser = "Event.findByUser";
    public static final String findByIdentifier = "Event.findByIdentifier";
    public static final String findByUserInvitationAccepted = "Event.findByUserInvitationAccepted";

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long identifier;

    //required by the Primefaces Schedule component
    @Transient
    private String id;
    @Transient
    private boolean loadedByOwner;
    @Transient
    private boolean loadedInPublicCalendar = false;

    //@Size(min=1,max=255, message = "Title cannot be empty")
    //@Column(nullable=false)
    private String title;

    @NotNull(message = "Mandatory field")
    @Temporal(TemporalType.TIMESTAMP)
    private Date startDate;

    @NotNull(message = "Mandatory field")
    @Temporal(TemporalType.TIMESTAMP)
    private Date endDate;

    private boolean outdoor;

    private boolean checkedOneDay;

    private boolean checkedThreeDays;

    @Transient
    String styleClass;

    @ManyToOne(cascade={CascadeType.DETACH, CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    private Location location;

    @OneToMany(cascade = ALL, mappedBy = "event")
    private List<InvitationRequest> invitationRequests;

    @OneToMany(mappedBy = "event")
    private List<WeatherAlert> weatherAlerts;

    //@Column(columnDefinition="FLOAT(6,2)")
    //private float forecastedTemperature;
    private boolean publicEvent;

    @ManyToOne
    private Calendar calendar;

    //private String pathIcon;   
    public Event() {
        this.checkedOneDay = false;
        this.checkedThreeDays = false;
        this.loadedByOwner = true;
    }

    public Event(Date startDate, Date endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
        this.checkedOneDay = false;
        this.checkedThreeDays = false;
        this.loadedByOwner = true;
    }

    public Event(String title, Boolean outdoor, Date startDate, Date endDate) {
        this.title = title;
        this.outdoor = outdoor;
        this.startDate = startDate;
        this.endDate = endDate;
        this.checkedOneDay = false;
        this.checkedThreeDays = false;
        this.loadedByOwner = true;
    }
    
    //@PrePersist
    private boolean emptyOrNull(String s) {
        return (s == null || s.isEmpty());
    }

    public void sanitizeLocation() {
        if (outdoor) {
            if (emptyOrNull(location.getDescription())
                    || emptyOrNull(location.getLatitude())
                    || emptyOrNull(location.getLongitude())) {

                location = null;
            }
        } else {
            if (emptyOrNull(location.getDescription())) {
                location = null;
            }
        }
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (identifier != null ? identifier.hashCode() : 0);
        return hash;
    }

    public Long getIdentifier() {
        return identifier;
    }

    public void setIdentifier(Long identifier) {
        this.identifier = identifier;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Event)) {
            return false;
        }
        Event other = (Event) object;
        if ((this.identifier == null && other.identifier != null) || (this.identifier != null && !this.identifier.equals(other.identifier))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.sunrise.entity.Event[ id=" + identifier + " ]";
    }

    @Override
    public String getId() {
        return this.id;
    }

    @Override
    public void setId(String string) {
        this.id = string;
    }

    @Override
    public Object getData() {
        return null;
    }

    @Override
    public String getTitle() {
        if (loadedInPublicCalendar) {
            if (this.isPublicEvent()) {
                return title;
            } else {
                return "[Private]";
            }
        }
        return title;
    }

    @Override
    public Date getStartDate() {
        return startDate;
    }

    @Override
    public Date getEndDate() {
        return endDate;
    }

    @Override
    public boolean isAllDay() {
        return false;
    }

    @Override
    public String getStyleClass() {
        return styleClass;
    }

    public void setStyleClass(String styleClass) {
        this.styleClass = styleClass;
    }

    @Override
    public boolean isEditable() {
        return this.loadedByOwner;
    }

    @Override
    public String getDescription() {
        return null;
    }

    /*
     public String getPathIcon() {
     return pathIcon;
     }

     public void setPathIcon(String pathIcon) {
     this.pathIcon = pathIcon;
     }
     */
    public void setStartDate(Date startDate) {
        //this.startDate = DateToTimestamp(startDate);
        this.startDate = startDate;
    }

    public void setEndDate(Date endDate) {
        //this.endDate = DateToTimestamp(endDate);
        this.endDate = endDate;
    }

    public boolean isOutdoor() {
        return outdoor;
    }

    public void setOutdoor(boolean outdoor) {
        this.outdoor = outdoor;
    }

    public boolean isCheckedOneDay() {
        return checkedOneDay;
    }

    public void setCheckedOneDay(boolean checkedOneDay) {
        this.checkedOneDay = checkedOneDay;
    }

    public boolean isCheckedThreeDays() {
        return checkedThreeDays;
    }

    public void setCheckedThreeDays(boolean checkedThreeDays) {
        this.checkedThreeDays = checkedThreeDays;
    }

    public Location getLocation() {
        if (location == null) {
            location = new Location();
        }
        return location;
    }

    public Location getLocationStandard() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    /*
     public float getForecastedTemperature() {
     return forecastedTemperature;
     }

     public void setForecastedTemperature(float forecastedTemperature) {
     this.forecastedTemperature = forecastedTemperature;
     }
     */
    public boolean isPublicEvent() {
        return publicEvent;
    }

    public void setPublicEvent(boolean publicEvent) {
        this.publicEvent = publicEvent;
    }

    public Calendar getCalendar() {
        return calendar;
    }

    public void setCalendar(Calendar calendar) {
        this.calendar = calendar;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isLoadedByOwner() {
        return loadedByOwner;
    }

    public void setLoadedByOwner(boolean loadedByOwner) {
        this.loadedByOwner = loadedByOwner;
    }

    public boolean isLoadedInPublicCalendar() {
        return loadedInPublicCalendar;
    }

    public void setLoadedInPublicCalendar(boolean loadedInPublicCalendar) {
        this.loadedInPublicCalendar = loadedInPublicCalendar;
    }

    /**
     * @return the invitationRequests
     */
    public List<InvitationRequest> getInvitationRequests() {
        if (invitationRequests == null) {
            invitationRequests = new ArrayList<InvitationRequest>();
        }
        return invitationRequests;
    }

    public void setInvitationRequests(List<InvitationRequest> invitationRequests) {
        if (invitationRequests == null) {
            invitationRequests = new ArrayList<InvitationRequest>();
        }
        this.invitationRequests = invitationRequests;
    }

    public void addInvitationRequest(InvitationRequest invitationRequest) {
        if (invitationRequests == null) {
            invitationRequests = new ArrayList<InvitationRequest>();
        }
        this.invitationRequests.add(invitationRequest);
    }
    
    public void removeInvitationRequest(InvitationRequest invitationRequest) {
        if (invitationRequests != null && invitationRequests.contains(invitationRequest)) {
            invitationRequests.remove(invitationRequest);
        }
    }

    public List<WeatherAlert> getWeatherAlerts() {
        if (weatherAlerts == null) {
            weatherAlerts = new ArrayList<WeatherAlert>();
        }
        return weatherAlerts;
    }

    public Timestamp DateToTimestamp(Date date) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(date);
        cal.set(java.util.Calendar.MILLISECOND, 0);
        return new Timestamp(cal.getTimeInMillis());
    }

    public InvitationRequest findInvitationForUser(User u) {
        if (invitationRequests == null) {
            return null;
        }

        for (InvitationRequest inv : invitationRequests) {
            if (inv.getRecipient() == u) {
                return inv;
            }
        }
        return null;
    }

    public User getOwner() {
        if(calendar!=null) {
            return calendar.getOwner();
        }
        return null;
    }
    
}
